<!DOCTYPE html><html class="appearance-auto" lang="zh-CN"><head><meta charset="UTF-8"><title>【Spring源码解析系列】 Bean实例化策略InstantiationStrategy</title><meta name="description" content="用创业者心态做好每一件事情！"><meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, initial-scale=1"><!-- Google Analytics --><!-- End Google Analytics -->
<!-- Baidu Analytics --><!-- End Baidu Analytics --><link rel="icon" href="/blog/images/favicon.png"><link rel="stylesheet" href="/blog/style/common/bulma.css"><link rel="stylesheet" href="/blog/style/base.css"><link rel="stylesheet" href="/blog/style/common/helper.css"><script src="/blog/js/common.js"></script><link rel="stylesheet" href="/blog/style/post.css"><link rel="stylesheet" href="/blog/style/themes/highlight-theme-light.css"><script src="/blog/js/highlight.pack.js"></script><meta name="description" content="
本文主要讲述Spring中Bean实例化策略InstantiationStrategy


InstantiationStrategyInstantiationStrategy 接口定义了 Spring Bean 实例化的策略，根据创建对象情况的不同，提供了三种策略：无参构造方法、有参构造方法、工厂方法;
public interface InstantiationStrategy &amp;#123;
   /**
    * 默认构造方法
    */
   Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
         throws BeansException;
   /**
.."><!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 5.4.1"><link rel="alternate" href="/blog/atom.xml" title="janedler's blog" type="application/atom+xml">
</head><body class="is-flex is-flex-direction-column"><header class="header-widget is-flex-shrink-0 is-hidden-mobile"><div class="container is-fullhd is-flex is-justify-content-space-between is-align-items-center is-full-height"><section class="is-hidden-mobile is-flex-shrink-0"><h2><a href="/blog/">田园牧歌(*︶*)'s blog</a></h2></section><h3 class="is-hidden-mobile is-family-serif is-full-height is-flex is-align-items-center is-flex-shrink-0"><div class="is-full-height" id="postTopic"><p class="is-full-height is-flex-shrink-0 is-flex is-align-items-center is-justify-content-center">【Spring源码解析系列】 Bean实例化策略InstantiationStrategy</p><p class="is-full-height is-flex-shrink-0 is-flex is-align-items-center is-justify-content-center">点击返回顶部</p></div></h3><aside class="is-flex-shrink-0"><h3 class="is-inline-block"><a href="/blog/">首页</a></h3><h3 class="is-inline-block"><a href="/blog/about">关于</a></h3><h3 class="is-inline-block"><a href="/blog/archives">归档</a></h3></aside></div></header><header class="is-flex header-widget is-flex-shrink-0 is-align-items-center is-justify-content-center is-hidden-tablet"><h3 class="is-inline-block"><a href="/blog/">首页</a></h3><h3 class="is-inline-block"><a href="/blog/about">关于</a></h3><h3 class="is-inline-block"><a href="/blog/archives">归档</a></h3></header><main><main class="container is-max-widescreen content section post-page pt-4 px-4"><div class="columns is-flex-desktop is-justify-content-center is-flex-direction-row-reverse"><div class="column is-3 is-hidden-mobile"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#InstantiationStrategy"><span class="toc-text">InstantiationStrategy</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#SimpleInstantiationStrategy"><span class="toc-text">SimpleInstantiationStrategy</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#CglibSubclassingInstantiationStrategy"><span class="toc-text">CglibSubclassingInstantiationStrategy</span></a></li></ol></li></ol></div><div class="column is-9"><header class="my-4"><a href="/blog/tags/Java"><i class="tag post-item-tag">Java</i></a><a href="/blog/tags/Spring"><i class="tag post-item-tag">Spring</i></a></header><h1 class="mt-0 mb-1 is-family-serif" id="postTitle">【Spring源码解析系列】 Bean实例化策略InstantiationStrategy</h1><time class="has-text-grey" datetime="2022-11-30T16:00:00.000Z">2022-12-01</time><article class="mt-2 post-content"><p><img src="https://janedler.oss-cn-beijing.aliyuncs.com/images/spring.png" alt="cover"></p>
<p>本文主要讲述Spring中Bean实例化策略InstantiationStrategy</p>
<span id="more"></span>

<h2 id="InstantiationStrategy"><a href="#InstantiationStrategy" class="headerlink" title="InstantiationStrategy"></a>InstantiationStrategy</h2><p>InstantiationStrategy 接口定义了 Spring Bean 实例化的策略，根据创建对象情况的不同，提供了三种策略：无参构造方法、有参构造方法、工厂方法;</p>
<pre><code class="java">public interface InstantiationStrategy &#123;
   /**
    * 默认构造方法
    */
   Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
         throws BeansException;
   /**
    * 指定构造方法
    */
   Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
         Constructor&lt;?&gt; ctor, Object... args) throws BeansException;
   /**
    * 工厂方法
    * 实例化工厂的同时不会把bean实例化，又称为延迟加载，只有用户访问bean时才会把bean实例化
    */
   Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
         @Nullable Object factoryBean, Method factoryMethod, Object... args)
         throws BeansException;
&#125;
</code></pre>
<p>InstantiationStrategy 接口有两个实现类：SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy</p>
<h3 id="SimpleInstantiationStrategy"><a href="#SimpleInstantiationStrategy" class="headerlink" title="SimpleInstantiationStrategy"></a>SimpleInstantiationStrategy</h3><p>① 如果是工厂方法实例化，则直接使用反射创建对象</p>
<pre><code class="java">//使用初始化策略实例化Bean对象
//工厂方法
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
      @Nullable Object factoryBean, final Method factoryMethod, Object... args) &#123;
   try &#123;
      // 设置 Method 可访问
      ReflectionUtils.makeAccessible(factoryMethod);
      // 获得原 Method 对象
      Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
      try &#123;
         // 设置新的 Method 对象，到 currentlyInvokedFactoryMethod 中
         currentlyInvokedFactoryMethod.set(factoryMethod);
         // 创建 Bean 对象
         Object result = factoryMethod.invoke(factoryBean, args);
         if (result == null) &#123;
            // 未创建，则创建 NullBean 对象
            result = new NullBean();
         &#125;
         return result;
      &#125;
      finally &#123;
         if (priorInvokedFactoryMethod != null) &#123;
            // 设置老的 Method 对象，到 currentlyInvokedFactoryMethod 中
            currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
         &#125;
         else &#123;
            currentlyInvokedFactoryMethod.remove();
         &#125;
      &#125;
   &#125;
   ...省略...
&#125;
</code></pre>
<p>② 如果是构造方法实例化，则是先判断是否有 MethodOverrides，如果没有则是直接使用反射，如果有则就需要 <a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=CGLIB&spm=1001.2101.3001.7020">CGLIB</a> 实例化对象</p>
<pre><code class="java">//使用初始化策略实例化Bean对象
//默认构造方法
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) &#123;
   // Don&#39;t override the class with CGLIB if no overrides.
   //如果Bean定义中没有方法覆盖，没有实现AbstractBeanDefinition，则就不需要CGLIB父类类的方法
   //Spring AOP 默认为 AOP 代理使用标准的 JDK 动态代理。这允许代理任何接口（或接口集）。
   //Spring AOP 也可以使用 CGLIB 代理。这是代理类而不是接口所必需的。默认情况下，如果业务对象未实现接口，则使用 CGLIB。
   //hasMethodOverrides:lookup-method,replaced-method
   if (!bd.hasMethodOverrides()) &#123;
      Constructor&lt;?&gt; constructorToUse;
      synchronized (bd.constructorArgumentLock) &#123;
         //获取对象的构造方法或工厂方法
         constructorToUse = (Constructor&lt;?&gt;) bd.resolvedConstructorOrFactoryMethod;
         //如果没有构造方法且没有工厂方法
         if (constructorToUse == null) &#123;
            //使用JDK的反射机制，判断要实例化的Bean是否是接口
            final Class&lt;?&gt; clazz = bd.getBeanClass();
            if (clazz.isInterface()) &#123;
               throw new BeanInstantiationException(clazz, &quot;Specified class is an interface&quot;);
            &#125;
            try &#123;
               //通过发射机制获取Bean的构造方法
               constructorToUse = clazz.getDeclaredConstructor();
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            &#125;
            catch (Throwable ex) &#123;
               throw new BeanInstantiationException(clazz, &quot;No default constructor found&quot;, ex);
            &#125;
         &#125;
      &#125;
      //使用BeanUtils实例化，通过发射机制调用“构造方法.newInstance(arg)”来进行实例化
      return BeanUtils.instantiateClass(constructorToUse);
   &#125;
   else &#123;
      // Must generate CGLIB subclass.
      //使用CGLIB来实例化对象
      return instantiateWithMethodInjection(bd, beanName, owner);
   &#125;
&#125;

//使用初始化策略实例化Bean对象
//指定构造方法
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
      final Constructor&lt;?&gt; ctor, Object... args) &#123;
   // 没有覆盖，直接使用反射实例化即可
   if (!bd.hasMethodOverrides()) &#123;
      // 通过 BeanUtils 直接使用构造器对象实例化 Bean 对象 JDK
      return BeanUtils.instantiateClass(ctor, args);
   &#125;
   else &#123;
      // 生成 CGLIB 创建的子类对象
      return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
   &#125;
&#125;
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,@Nullable Constructor&lt;?&gt; ctor, Object... args) &#123;
        return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
&#125;
</code></pre>
<h3 id="CglibSubclassingInstantiationStrategy"><a href="#CglibSubclassingInstantiationStrategy" class="headerlink" title="CglibSubclassingInstantiationStrategy"></a>CglibSubclassingInstantiationStrategy</h3><pre><code class="java">//使用CGLIB进行Bean对象的实例化
public Object instantiate(@Nullable Constructor&lt;?&gt; ctor, Object... args) &#123;
   //通过 Cglib 创建一个代理类
   Class&lt;?&gt; subclass = createEnhancedSubclass(this.beanDefinition);
   Object instance;
   //没有构造器，通过 BeanUtils 使用默认构造器创建一个bean实例
   if (ctor == null) &#123;
      instance = BeanUtils.instantiateClass(subclass);
   &#125;
   else &#123;
      try &#123;
         // 获取代理类对应的构造器对象，并实例化 bean
         Constructor&lt;?&gt; enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
         instance = enhancedSubclassConstructor.newInstance(args);
      &#125;
      catch (Exception ex) &#123;
         throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
               &quot;Failed to invoke constructor for CGLIB enhanced subclass [&quot; + subclass.getName() + &quot;]&quot;, ex);
      &#125;
   &#125;
   // SPR-10785: set callbacks directly on the instance instead of in the
   // enhanced class (via the Enhancer) in order to avoid memory leaks.
   // 为了避免 memory leaks 异常，直接在 bean 实例上设置回调对象
   Factory factory = (Factory) instance;
   factory.setCallbacks(new Callback[] &#123;NoOp.INSTANCE,
         new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
         new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)&#125;);
   return instance;
&#125;
</code></pre>
<pre><code class="java">public Class&lt;?&gt; createEnhancedSubclass(RootBeanDefinition beanDefinition) &#123;
   //CGLIB里面的类
   Enhancer enhancer = new Enhancer();
   //将Bean本身作为其基类
   enhancer.setSuperclass(beanDefinition.getBeanClass());
   enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
   enhancer.setAttemptLoad(true);
   if (this.owner instanceof ConfigurableBeanFactory) &#123;
      ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
      enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
   &#125;
   enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
   enhancer.setCallbackTypes(CALLBACK_TYPES);
   //使用CGLIB的create方法生成实例对象
   return enhancer.createClass();
&#125;
</code></pre>
</article><section class="jump-container is-flex is-justify-content-space-between my-6"><!-- em is empty placeholder--><a class="button is-default" href="/blog/2022/12/01/Spring/Spring%E6%89%A9%E5%B1%95%E5%8A%9F%E8%83%BD-BeanFactoryPostProcessor/" title="【Spring源码解析系列】 BeanFactoryPostProcessor"><i class="iconfont icon-prev mr-2 has-text-grey"></i><span class="has-text-weight-semibold">上一页: 【Spring源码解析系列】 BeanFactoryPostProcessor</span></a><a class="button is-default" href="/blog/2022/12/01/Spring/Spring%E9%AB%98%E7%BA%A7%E7%89%B9%E6%80%A7-lazy-init%E9%A2%84%E5%88%9D%E5%A7%8B%E5%8C%96/" title="【Spring源码解析系列】 lazy-init预初始化"><span class="has-text-weight-semibold">下一页: 【Spring源码解析系列】 lazy-init预初始化</span><i class="iconfont icon-next ml-2 has-text-grey"></i></a></section><article class="mt-6 comment-container"><script async repo="janedler/blog" src="https://utteranc.es/client.js" issue-term="pathname" theme="preferred-color-scheme"></script></article></div></div></main></main><footer class="is-flex is-flex-direction-column is-align-items-center is-flex-shrink-0 is-family-serif"><section class="sns-container"><!-- Github--><a title="github" target="_blank" rel="noopener nofollow" href="//github.com//janedler"><i class="iconfont icon-github"></i></a><!-- Ins--><!-- RSS--><a title="rss" target="_blank" rel="noopener nofollow" href="/blog/atom.xml"><i class="iconfont icon-rss"></i></a><!-- 知乎--><!-- 领英--><!-- 脸书--></section><p><span>Copyright ©</span><span> 田园牧歌(*︶*) 2022</span></p><div class="is-flex is-justify-content-center is-flex-wrap-wrap"><p>Powered by Hexo &verbar;&nbsp;</p><p class="is-flex is-justify-content-center"><a title="Hexo theme author" target="_blank" rel="noopener" href="//github.com/haojen">Theme by Haojen&nbsp;</a></p><div style="margin-top: 2px"><a class="github-button" title="github-button" target="_blank" rel="noopener" href="https://github.com/haojen/hexo-theme-Claudia" data-color-scheme="no-preference: light; light: light; dark: dark;" data-show-count="true"></a></div></div><div><span></span></div></footer><script async defer src="https://buttons.github.io/buttons.js"></script><script src="/blog/js/post.js"></script></body></html>